/**
 *
 */
package 反射;

import java.beans.BeanInfo;
import java.beans.IntrospectionException;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import jdk8.User;

/**
 * @Title:
 * @author zhoujie
 * @date 2018年6月26日 下午8:33:03 
 *
 */
public class Demo {
    public static void main(String[] args) throws IntrospectionException, IllegalAccessException, IllegalArgumentException, InvocationTargetException {
        User u = new User(1, "sky");
        BeanInfo beanInfo = Introspector.getBeanInfo(User.class);
        Map<String, Method> methodMap = new HashMap<>();
        for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
            System.out.println(pd.getName());
            System.out.println(pd.getReadMethod().invoke(u, null));
        }
    }

    public static <T> List<Map<String, Object>> copy2List(Collection<? extends T> objs, Class<? super T> clazz,
                                                          Map<String, String> nullVals, Collection<String> props) {
        if (objs.isEmpty()) {
            return Collections.emptyList();
        }

        List<Map<String, Object>> rows = new ArrayList<>();
        try {
            BeanInfo beanInfo = Introspector.getBeanInfo(clazz);
            Map<String, Method> methodMap = new HashMap<>();
            for (PropertyDescriptor pd : beanInfo.getPropertyDescriptors()) {
                if (pd.getName() != null && pd.getReadMethod() != null)
                    methodMap.put(pd.getName(), pd.getReadMethod());
            }

            String val;
            Method method;
            for (Object obj : objs) {
                Map<String, Object> map = new HashMap<>();
                for (String name : props) {
                    if (!(method = methodMap.get(name)).isAccessible()) {
                        method.setAccessible(true);
                    }

                    Object value = method.invoke(obj);
                    if (value == null) {
                        if ((val = (nullVals == null ? null : nullVals.get(name))) == null) {
                            val = defaultString(method.getReturnType());
                        }
                    } else {
                        val = toString(value);
                    }

                    map.put(name, val);
                }

                rows.add(map);
            }
        } catch (ReflectiveOperationException | IntrospectionException e) {
            e.printStackTrace();
            throw new ClassCastException(e.getMessage());
        }
        return rows;
    }

    /**
     * 根据类型获取缺省字符串
     *
     * @param clazz 类型
     * @return
     */
    public static String defaultString(Class<?> clazz) {
        if (clazz == BigDecimal.class // 大数字
                || clazz == Float.class || clazz == Double.class // 包装类型
                || clazz == float.class || clazz == double.class) { // 基本类型
            return "0.00";
        } else if (clazz == BigInteger.class // 大数字
                || clazz == Integer.class || clazz == Long.class || clazz == Short.class // 包装类型
                || clazz == int.class || clazz == long.class || clazz == short.class) { // 基础类型
            return "0";
        }
        return "";
    }

    /***
     * 对象转成字符串
     *
     * @param o
     * @return
     */
    public static <T> String toString(T o) {
        if (o == null) {
            return "";
        }

        Class<?> clazz = o.getClass();
        if (clazz == String.class) {
            return String.valueOf(o);
        } else if (clazz == BigDecimal.class // 大数字
                || clazz == Float.class || clazz == Double.class // 包装类型
                || clazz == float.class || clazz == double.class) { // 基本类型
            return String.format("%.2f", o);
        } else if (clazz == BigInteger.class // 大数字
                || clazz == Integer.class || clazz == Long.class || clazz == Short.class // 包装类型
                || clazz == int.class || clazz == long.class || clazz == short.class) { // 基础类型
            return o.toString();
        } else {
            return o.toString();
        }
    }

}
